#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include "errWaveFunction.h"
#include "SqliteInterface.h"
#include <time.h>
#include "../allThread.h"
#include "../RealtimeWaveform.h"
#include "../ErrorLog.h"
#include "../modbus/create_modbus_custom_slave.h"
#include "errWaveFunction.h"

#define ERROR_LOG_SQL_TABLE "ErrorLogTable"
static int errRspLen = 0;

static int errorInfoCallback(void *buf, int argc, char **argv, char **azColName){

    char timestamp[20];
    uint8_t* rsp = (uint8_t*) buf;
    
    for (int i = 0; i < argc; i++) {
        if (strcmp(azColName[i], "ErrorID") == 0) {
            rsp[(errRspLen++) + 2] = (uint8_t)(atoi(argv[i]) >> 8);
            rsp[(errRspLen++) + 2] = (uint8_t)atoi(argv[i]);
            printf("error ID: %d\n", atoi(argv[i]));
        }
        if (strcmp(azColName[i], "ErrorTimeStamp") == 0) {
            time_t errTime = atoi(argv[i]);
            struct tm* errTm = localtime(&errTime);
            rsp[(errRspLen++) + 2] = (uint8_t)((errTm->tm_year + 1900) >> 8);
            rsp[(errRspLen++) + 2] = (uint8_t)(errTm->tm_year + 1900);
            rsp[(errRspLen++) + 2] = (uint8_t)((errTm->tm_mon + 1) >> 8);
            rsp[(errRspLen++) + 2] = (uint8_t)(errTm->tm_mon + 1);
            rsp[(errRspLen++) + 2] = (uint8_t)((errTm->tm_mday) >> 8);
            rsp[(errRspLen++) + 2] = (uint8_t)(errTm->tm_mday); 
            rsp[(errRspLen++) + 2] = (uint8_t)((errTm->tm_hour) >> 8);
            rsp[(errRspLen++) + 2] = (uint8_t)(errTm->tm_hour);   
            rsp[(errRspLen++) + 2] = (uint8_t)((errTm->tm_min) >> 8);
            rsp[(errRspLen++) + 2] = (uint8_t)(errTm->tm_min); 
            rsp[(errRspLen++) + 2] = (uint8_t)((errTm->tm_sec) >> 8);
            rsp[(errRspLen++) + 2] = (uint8_t)(errTm->tm_sec); 
            rsp[(errRspLen++) + 2] = 0;
            rsp[(errRspLen++) + 2] = 0;  
            strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", errTm);
            printf("error time stamp: %s\n", timestamp);
        }
    }
    rsp[0] = 0;
    rsp[1] += 1;

    return 0;
}

static int errorSpecCallback(void *buf, int argc, char **argv, char **azColName){

    char timestamp[20];
    uint8_t* rsp = (uint8_t*) buf;

    struct errorlogFileHead* errorHead = getErrorlogHeadBuff();
    struct errorWaveData* errorWaveData = getErrorWaveDataBuff();
    memset(errorHead, 0, sizeof(struct errorlogFileHead));
    memset(errorWaveData, 0, sizeof(struct errorWaveData));
    
    for (int i = 0; i < argc; i++) {
        if(strcmp(azColName[i], "ErrorID") == 0){
            errorHead->elfh_errorId = atoi(argv[i]);
            printf("error id: %d\n", atoi(argv[i]));
        }
        if(strcmp(azColName[i], "ErrorTimeStamp") == 0){
            time_t errTime = atoi(argv[i]);
            struct tm* errTm = localtime(&errTime);
            errorHead->elfh_time.year = errTm->tm_year + 1900;
            errorHead->elfh_time.mon = errTm->tm_mon + 1;
            errorHead->elfh_time.day = errTm->tm_mday;
            errorHead->elfh_time.hour = errTm->tm_hour;
            errorHead->elfh_time.min = errTm->tm_min;
            errorHead->elfh_time.sec = errTm->tm_sec;
            errorHead->elfh_time.ms = 0; 
            strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", errTm);
            printf("error time stamp: %s\n", timestamp);
        }
        if(strcmp(azColName[i], "ErrorGroupIndex") == 0){
            errorHead->elfh_waveInfor.errorWaveDataGroupIndex = atoi(argv[i]);
            errorHead->elfh_pacByteQty = PAC_DATA_QTY * 2;
            errorHead->elfh_waveInfor.waveGroupQty = MAX_ERROR_WAVE_GROUP;
            errorHead->elfh_waveInfor.fifoQty = WAVEFORM_FIFO_QTY;
            errorHead->elfh_waveInfor.fifoDepth = WAVEFORM_FIFO_DEPTH;
            for(uint16_t fifoIndex = 0; fifoIndex < WAVEFORM_FIFO_QTY; fifoIndex++){
                errorHead->elfh_waveInfor.channelId[fifoIndex] = fifoIndex + 1;
            }
        }
        if(strcmp(azColName[i], "ErrorLogData") == 0){
            errorLogBuffDataFromJson(argv[i]);
        }
    }
    rsp[0] = 0;
    rsp[1] += 1;

    return 0;
}

static int logQtyCallback(void *buf, int argc, char **argv, char **azColName)
{
    int* errorQty = (int*)buf;

    if(strcmp(azColName[0], "rowNum") == 0){
        *errorQty = atoi(argv[0]);
    }

    return 0;
}

int readErrorLogHeadInfo(uint8_t* rsp){

    int length = 0;
    struct errorlogFileHead* errorHead = getErrorlogHeadBuff();

    rsp[0] = 1;
    length += 1;
    memcpy(&rsp[length], &(errorHead->elfh_errorId), sizeof(uint32_t));
    length += 8;
    memset(&rsp[length], 1, 16);
    length += 16;
    memset(&rsp[length], 2, 16);
    length += 16;
    memset(&rsp[length], 3, 16);
    length += 16;
    memset(&rsp[length], 4, 16);
    length += 16;
    memcpy(&rsp[length], &(errorHead->elfh_time.year), sizeof(uint32_t));
    length += 4;
    memcpy(&rsp[length], &(errorHead->elfh_time.mon), sizeof(uint32_t));
    length += 4;
    memcpy(&rsp[length], &(errorHead->elfh_time.day), sizeof(uint32_t));
    length += 4;
    memcpy(&rsp[length], &(errorHead->elfh_time.hour), sizeof(uint32_t));
    length += 4;
    memcpy(&rsp[length], &(errorHead->elfh_time.min), sizeof(uint32_t));
    length += 4;
    memcpy(&rsp[length], &(errorHead->elfh_time.sec), sizeof(uint32_t));
    length += 4;
    memcpy(&rsp[length], &(errorHead->elfh_time.ms), sizeof(uint32_t));
    length += 4;

    memcpy(&rsp[length], &(errorHead->elfh_pacByteQty), sizeof(uint32_t));
    length += 4;
    memcpy(&rsp[length], &(errorHead->elfh_waveInfor.waveGroupQty), sizeof(uint32_t));
    length += 4;
    memcpy(&rsp[length], &(errorHead->elfh_waveInfor.fifoQty), sizeof(uint32_t));
    length += 4;
    memcpy(&rsp[length], &(errorHead->elfh_waveInfor.fifoDepth), sizeof(uint32_t));
    length += 4;
    memcpy(&rsp[length], &(errorHead->elfh_waveInfor.errorWaveDataGroupIndex), sizeof(uint32_t));
    length += 4;
    memcpy(&rsp[length], errorHead->elfh_waveInfor.channelId, sizeof(errorHead->elfh_waveInfor.channelId));
    length += sizeof(errorHead->elfh_waveInfor.channelId);
    length += 4;

    return length;
}

int readErrorLogPACData(uint8_t* rsp){

    int length = 0;
    uint16_t pacData;

    rsp[0] = 1;
    uint16_t* pacDataBuff = getErrorLogPacDataBuff();

    for(int pacIndex = 0; pacIndex < PAC_DATA_QTY; pacIndex++){
        pacData = pacDataBuff[pacIndex];
        rsp[length++] = (uint8_t)(pacData >> 8);
        rsp[length++] = (uint8_t)pacData;
    }

    return length + 1;

}

int readErrorGroupWave(uint8_t groupIndex, uint8_t *rsp){

    int length = 0;
    uint16_t waveData;

    struct errorWaveData* errorWaveData = getErrorWaveDataBuff();

    rsp[0] = 1;
    rsp[1] = groupIndex;
    length = 2;
    for(int fifoIndex = 0; fifoIndex < WAVEFORM_FIFO_QTY; fifoIndex++){
        for(int dataIndex = 0; dataIndex < WAVEFORM_FIFO_DEPTH; dataIndex++){
            waveData = errorWaveData->errorWaveData[groupIndex].waveData[fifoIndex][dataIndex];
            rsp[length++] = (uint8_t)(waveData >> 8);
            rsp[length++] = (uint8_t)waveData;
        }
    }

    return length;
}

//获取数据库中总条数，所有的错误ID和时间
int readErrorLogInfo_db(uint8_t *rsp){

    char *zErrMsg = 0;
    int rc;

    char sql[100];
    int length = 0;

    rsp[0] = 0;
    rsp[1] = 0;

    sprintf(sql, "SELECT ErrorID, ErrorTimeStamp FROM %s;", ERROR_LOG_SQL_TABLE);
   
    rc = sqlite3_exec(db, sql, errorInfoCallback, rsp, &zErrMsg);
    if( rc != SQLITE_OK ){
        fprintf(stderr, "readErrorLogInfo_db SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
    } else {
        fprintf(stdout, "readErrorLogInfo_db Data retrieved successfully\n");
    }
    length = errRspLen + 2;
    errRspLen = 0; //需重置回0

    return length;
}

int readSpecErrorLog_db(int offset, uint8_t* rsp){

    char *zErrMsg = 0;
    int rc;

    char sql[200];
    int length = 0;

    sprintf(sql, "SELECT ErrorID, ErrorTimeStamp, ErrorGroupIndex, ErrorLogData FROM %s LIMIT %d OFFSET %d;", ERROR_LOG_SQL_TABLE, 1, offset - 1);
   
    rc = sqlite3_exec(db, sql, errorSpecCallback, rsp, &zErrMsg);
    if( rc != SQLITE_OK ){
        fprintf(stderr, "readSpecErrorLog_db SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
        rsp[0] = 0;
    } else {
        fprintf(stdout, "readSpecErrorLog_db Data retrieved successfully\n");
        rsp[0] = 1;
    }
    length = 1;
    errRspLen = 0; //需重置回0

    return length;
}

//查询存了多少条数据
int errorLogQty(int* errQty){

    char *zErrMsg = 0;
    int rc;
    
    char sql[100];
    sprintf(sql, "SELECT count(*) AS rowNum FROM %s;", ERROR_LOG_SQL_TABLE);
   
    rc = sqlite3_exec(db, sql, logQtyCallback, errQty, &zErrMsg);
    if( rc != SQLITE_OK ){
        fprintf(stderr, "SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
        return -1;
    } else {
        fprintf(stdout, "errorLogQty [%d] Data retrieved successfully\n", *errQty);
    }
    return 0;

}

//删除最老的一条错误日志记录
int deleteErrorLog_db(){

    char *zErrMsg = 0;
    int rc;
    
    char sql[200];
    sprintf(sql, "DELETE FROM %s WHERE id IN (SELECT id FROM ErrorLogTable LIMIT 1);", ERROR_LOG_SQL_TABLE);
   
    rc = sqlite3_exec(db, sql, 0, 0, &zErrMsg);
    if( rc != SQLITE_OK ){
        fprintf(stderr, "SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
        return -1;
    } else {
        fprintf(stdout, "Data deleted successfully\n");
        return 0;
    }
}

int insertErrorLog_db(int errorId, time_t errTime, uint32_t groupIndex, const char* strErrorLogData){

    static char errLogSql[600000];
    if(strErrorLogData == NULL){
        printf("json数据为空\n");
        return -1;
    }

    int ret;
    char *zErrMsg = 0;

    sprintf(errLogSql,"INSERT INTO %s (ErrorID, ErrorTimeStamp, ErrorGroupIndex, ErrorLogData) VALUES (%d, %ld, %d, '%s');",
            ERROR_LOG_SQL_TABLE, errorId, errTime, groupIndex, strErrorLogData);

    ret = sqlite3_exec(db, errLogSql, 0, 0, &zErrMsg);

    if (ret != SQLITE_OK)
    {
        printf(" __DATE__: %s ,__TIME__: %s ,__FILE__: %s ,__FUNCTION__: %s ,__LINE__: %d sqlite3_exec errWaveSql SQL error, %s\n",
               __DATE__, __TIME__, __FILE__, __func__, __LINE__,zErrMsg);

        sqlite3_free(zErrMsg);
        return -1;
    }
    else
    {
        printf("error log data is successfully inserted.\n");
    }
    return SQLITE_OK;   
}
